#include "netfd_hashmap.h"
#define VAR_NAME_TO_STR(var) #var


static uint32_t hash(const void* key, int len, uint32_t seed);

// 创建一个固定容量的哈希表
Netfd_HashMap* hashmap_netfd_create() {
	Netfd_HashMap* map = (Netfd_HashMap*)calloc(HASHMAP_CAPACITY, sizeof(Netfd_HashMap));
    if (map == NULL) {
        DEBUG_PRINT("哈希表创建失败！\n");
        //exit(1);
        return NULL;
    }
	map->length = HASHMAP_CAPACITY;
	map->hash_seed = time(NULL);

    /* DEBUG_PRINT("哈希表创建成功！\n"); */
    return map;
}


// 销毁一个哈希表
void hashmap_netfd_destroy(Netfd_HashMap* map) {
    //map->length = 0;
    map->hash_seed = 0;
    for (int i = 0; i < map->length; i++) {
        while (map->buckets[i]!=NULL) {
            Netfd_KeyValueNode* temp = map->buckets[i];
            map->buckets[i] = map->buckets[i]->next;
            free(temp);
        }
    }
    map->length = 0;
    free(map);
    map = NULL;
    DEBUG_PRINT("哈希表%s已销毁！\n", VAR_NAME_TO_STR(map));
}

// 插入一个键值对
ValueType_netfd hashmap_netfd_put(Netfd_HashMap* map, KeyType_netfd key, ValueType_netfd val) {
    ValueType_netfd old_val;
    uint32_t hash_value = hash(key, strlen(key), map->hash_seed);
    int i = hash_value % map->length;

    DEBUG_PRINT("键值对开始创建!key值是%s\n",key);

    Netfd_KeyValueNode* new_node = (Netfd_KeyValueNode*)calloc(1, sizeof(Netfd_KeyValueNode));
    if (new_node == NULL) {
        DEBUG_PRINT("节点创建失败！\n");
        return 0;
    }
    new_node->key = key;
    new_node->val = val;
    new_node->next = NULL;
    
    Netfd_KeyValueNode* temp = map->buckets[i];
    while (temp != NULL) {
        if (strcmp(temp->key,key) == 0) {
            old_val = temp->val;
            temp->val = new_node->val;
            return old_val;
        }  
        temp = temp->next;
    }
    new_node->next = map->buckets[i];
    map->buckets[i] = new_node;
    /* new_node->next = NULL; */
    DEBUG_PRINT("键值对创建成功!key值是%s\n",key);
    free(temp);
    return val;
}
// 查询一个键值对
ValueType_netfd hashmap_netfd_get(Netfd_HashMap* map, KeyType_netfd key) {
    ValueType_netfd res_value;
    uint32_t hash_value = hash(key, strlen(key), map->hash_seed);
    int i = hash_value % map->length;
    Netfd_KeyValueNode* temp = map->buckets[i];
    while (temp != NULL) {
        if (strcmp(temp->key,key)==0) {
            res_value = temp->val;
            DEBUG_PRINT("找到该键值对,已返回！\n");
            return res_value;
        }
        temp = temp->next;
    }
    free(temp);
    /* DEBUG_PRINT("未找到该键值对！\n"); */
    return 0;
}
// 删除某个键值对
int hashmap_netfd_remove(Netfd_HashMap* map, KeyType_netfd key) {

    uint32_t hash_value = hash(key, strlen(key), map->hash_seed);
    int i = hash_value % map->length;

    Netfd_KeyValueNode* previous = NULL;
    Netfd_KeyValueNode* temp = map->buckets[i];
    while (temp != NULL) {
        if (temp->key == key) {
            if (previous == NULL) {
                map->buckets[i] = temp->next;
                free(temp);
                DEBUG_PRINT("键值对已删除！\n");
                return 0;
            }
            previous->next = temp->next;
            free(temp);
            printf("键值对已删除！\n");
            return 0; 
        }
        previous = temp;
        temp = temp->next;
    }
    free(temp);
    /* printf("未找到对应的键值对！\n"); */
    return -1;
}

/* murmur_hash2 */
static uint32_t hash(const void* key, int len, uint32_t seed) {
    const uint32_t m = 0x5bd1e995;
    const int r = 24;
    uint32_t h = seed ^ len;
    const unsigned char* data = (const unsigned char*)key;

    while (len >= 4) {
        uint32_t k = *(uint32_t*)data;
        k *= m;
        k ^= k >> r;
        k *= m;
        h *= m;
        h ^= k;
        data += 4;
        len -= 4;
    }

    switch (len) {
    case 3: h ^= data[2] << 16;
    case 2: h ^= data[1] << 8;
    case 1: h ^= data[0];
        h *= m;
    };

    h ^= h >> 13;
    h *= m;
    h ^= h >> 15;

    return h;
}

int print_netfd_hashmap(Netfd_HashMap* map){
    if(map == NULL){
        printf("negative hashmap\n");
        return -1;
    }

    Netfd_KeyValueNode* current = map->buckets[0];
    for(int i = 0;i < HASHMAP_CAPACITY; i++){
        current = map->buckets[i];
        while(current!=NULL){
            printf("%d ",current->val);
            current = current->next;
        }
    }
    printf("\n");
    printf("打印完毕\n");
    return 0;
}

int hashmap_netfd_remove_all(Netfd_HashMap* map,int* idx_fd){
    if(map == NULL){
        return -1;
    }

    Netfd_KeyValueNode* current = map->buckets[0];
    for(int i = 0;i < HASHMAP_CAPACITY; i++){
        current = map->buckets[i];
        while(current!=NULL){
            close(current->val);
            idx_fd[current->val] = -1;
            hashmap_netfd_remove(map,current->key);
            current = map->buckets[i];
        }
    }
    return 0;
}


/* int main(){ */
/*     HashMap* map = hashmap_create(); */

/*     hashmap_put(map,"4",4); */
/*     hashmap_put(map,"5",5); */
/*     hashmap_put(map,"6",6); */
/*     hashmap_put(map,"7",7); */
/*     hashmap_put(map,"8",8); */

/*     int keyvalue; */

/*     keyvalue = hashmap_get(map,"4"); */
/*     printf("find it val = %d\n",keyvalue); */

/*     keyvalue = hashmap_get(map,"5"); */
/*     printf("find it val = %d\n",keyvalue); */
/*     keyvalue = hashmap_get(map,"6"); */
/*     printf("find it val = %d\n",keyvalue); */
/*     keyvalue = hashmap_get(map,"7"); */
/*     printf("find it val = %d\n",keyvalue); */

/*     keyvalue = hashmap_get(map,"8"); */
/*     printf("find it val = %d\n",keyvalue); */
    
/*     print_hashmap(map); */


/*     hashmap_remove(map,"8"); */
/*     keyvalue = hashmap_get(map,"8"); */
/*     printf("find it val = %d\n",keyvalue); */

/*     printf("--------------------\n"); */

/*     print_hashmap(map); */
/*     printf("--------------------\n"); */
/*     hashmap_remove_all(map); */

/*     printf("--------------------\n"); */
/*     print_hashmap(map); */
/* } */
